package com.letv.ads.util;

import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.webkit.WebView;
import com.letv.adlib.sdk.types.AdElementMime;
import com.letv.ads.bean.ADJSInBean;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * com.letv.ads.util
 * <p/>
 * Created by leiyao on 15-5-12 下午8:05.
 */
public class AdJSBridge implements IAdJSBridge, SensorEventListener {
    private static final int SENSOR_TYPE_ORIENTATION = 3;
    public final static int CLOSE_WEBVIEW = 1;
    public final static int REFRESH_WEBVIEW = 2;
    //全屏webview
    public final static int FULLSCREEN_WEBVIEW = 3;
    // 还原webview尺寸
    public final static int RESTORE_SIZE_WEBVIEW = 4;
    private static final String RESULT_SUCCEED = "{\"result\": 200}";
    private static final String RESULT_FAIL = "{\"result\": 400}";
    private static final String RESULT_CANNELED = "{\"result\": 201}";
    private static final String TAG = "ad_js";
    private Context mContext;
    private WebView mWebView;
    private Handler mHandler;
    private View mView;
    private Vibrator mVibrator;
    private int mRawWidth, mRawHeight;
    //定义sensor管理器
    private SensorManager mSensorManager;
    private boolean hasRegistSensor = false;
    private List<Integer> mRegistedSensorTypeList = new ArrayList<Integer>();
    private SensorAdJsBridge mSensorJSBean = null;
    // 上次检测时间
    private long lastUpdateTime;
    float[] accelerometerValues = new float[3];
    float[] magneticFieldValues = new float[3];

    //
    private AdElementMime mAdElement;
    // 程序可以在任意时刻传入ad元素
    public void setAdElement(AdElementMime mAdElement) {
        this.mAdElement = mAdElement;
    }


    public AdJSBridge() {
    }

    public AdJSBridge(AdElementMime adElement) {
        this.mAdElement = adElement;
    }

    /**
     * 组成调用JS方法的字符串，供loadUrl使用
     *
     * @param funcName   JS的方法名
     * @param callbackId
     * @param result     返回给JS的Json串
     * @return
     */
    public static String buildupJSCallString(String funcName, String callbackId, String result) {
//      javascript:LetvJSBridge.fireEvent('letv_bridge_1406795025490621','true')
        StringBuilder builder = new StringBuilder();
        builder.append("javascript:");
        builder.append(funcName);
        builder.append("(");
        builder.append("'" + callbackId + "'");
        builder.append(",");
        builder.append("'" + result + "'");
        builder.append(");");
        return builder.toString();
    }

    public void setJSBridge(Context activity, WebView webView, Handler handler, View root) {
        this.mContext = activity;
        this.mWebView = webView;
        this.mHandler = handler;
        this.mView = root;
        mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);

        this.mWebView.addJavascriptInterface(this, "LetvAdJSBridge_For_Android");

        int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        this.mWebView.measure(w, h);

        mRawWidth = this.mWebView.getWidth();
        mRawHeight = this.mWebView.getHeight();

    }

    @Override
    public void setJSBridge(Activity context, WebView webView, Handler handler, View root) {
        this.mContext = context;
        this.mWebView = webView;
        this.mHandler = handler;
        this.mView = root;
        mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);

        this.mWebView.addJavascriptInterface(this, "LetvAdJSBridge_For_Android");

        int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        this.mWebView.measure(w, h);

        mRawWidth = this.mWebView.getWidth();
        mRawHeight = this.mWebView.getHeight();
    }

    public void destory() {
        if (hasRegistSensor && mSensorManager != null) {
            mSensorManager.unregisterListener(this);
            mSensorManager = null;
        }
        mSensorJSBean = null;
    }

    /**
     * 震动
     * [{"name":{"type":"vibrate","pattern":[],"milliseconds":3000},"callback_id":"letv_bridge_14326294857127916","callback":"LetvJSBridge.fireEvent","func":"ad.fun.vibrate"}]
     */

    public void ad_func_vibrate(String json) {
        LogInfo.log(TAG, "ad_func_vibrate " + json);
        if (mVibrator == null) {
            return;
        }
        ADJSInBean adjsInBean = parseJsonArray(json);

        try {
            final JSONObject jo = new JSONObject(adjsInBean.getName());
            if (jo.has("pattern")) {
                JSONArray jsonArray = jo.getJSONArray("pattern");
                if (jsonArray != null && jsonArray.length() > 0) {
                    long[] pattern = new long[jsonArray.length()];
                    for (int i = 0; i < jsonArray.length(); ++i) {
                        pattern[i] = jsonArray.getLong(i);
                    }

                    int repeat = 1;
                    if (jo.has("repeat")) {
                        repeat = jo.getInt("repeat");
                    }
                    mVibrator.vibrate(pattern, repeat);
                }
            } else if (jo.has("milliseconds")) {
                long milliseconds = jo.getLong("milliseconds");
                mVibrator.vibrate(milliseconds);
            } else {
                mVibrator.vibrate(500);
            }
            callBackForJS(adjsInBean, true);
        } catch (JSONException jsonEx) {
            callBackForJS(adjsInBean, false);
        }


    }

    /**
     * 关闭webview
     */
    public void ad_func_close(String json) {
        if (mHandler != null) {
            LogInfo.log(TAG, "ad_func_close");
            ADJSInBean jsInBean = parseJsonArray(json);
            mHandler.sendEmptyMessage(CLOSE_WEBVIEW);
            callBackForJS(jsInBean, true);
        }
    }

    /**
     * webview全屏
     */
    public void ad_func_fullscreen(String json) {
        if (mHandler != null) {
            LogInfo.log(TAG, "ad_func_fullscreen");
            ADJSInBean jsInBean = parseJsonArray(json);
            mHandler.sendEmptyMessage(FULLSCREEN_WEBVIEW);
            HashMap<String, Object> screenInfo = new HashMap<String, Object>();
            Display display = ((WindowManager) this.mContext.getSystemService(Context.WINDOW_SERVICE))
                    .getDefaultDisplay();

            screenInfo.put("width", display.getWidth());
            screenInfo.put("height", display.getHeight());
            screenInfo.put("orientation", this.mContext.getResources().getConfiguration().orientation);

            callBackForJS(jsInBean, screenInfo);

        }
    }

    /**
     * 恢复原始webview尺寸
     */
    public void ad_func_restore(String json) {
        if (mHandler != null) {
            LogInfo.log(TAG, "ad_func_restore");
            ADJSInBean jsInBean = parseJsonArray(json);
            try {
                final JSONObject jo = new JSONObject(jsInBean.getName());
                int width, height;
                // 如果有传入的尺寸则用传入的尺寸缩放，否则用原有尺寸缩放
                if (jo.has("width") && jo.has("width")) {
                    width = jo.getInt("width");
                    height = jo.getInt("height");
                } else {
                    width = this.mRawWidth;
                    height = this.mRawHeight;
                }
                Message msg = mHandler.obtainMessage();
                msg.what = RESTORE_SIZE_WEBVIEW;
                msg.arg1 = width;
                msg.arg2 = height;
                mHandler.sendMessage(msg);
                callBackForJS(jsInBean, true);
            } catch (Exception e) {

            }
        }
    }

    /**
     * 注册感应器
     *
     * @param json
     */
    public void ad_func_regsensor(String json) {
        if (mSensorManager == null) {
            mSensorManager = (SensorManager) this.mContext.getSystemService(Context.SENSOR_SERVICE);
            hasRegistSensor = true;
        }
        if (mHandler != null) {
            LogInfo.log(TAG, "ad_func_regsensor");
            SensorAdJsBridge jsInBean = parseSensorJsonArray(json);
            try {
                JSONObject jsonObject = new JSONObject(jsInBean.getName());
                if (mSensorJSBean != null || hasRegistSensor) {
                    mSensorManager.unregisterListener(this);
                }
                mSensorJSBean = jsInBean;

                if (jsonObject.has("speed")) {
                    mSensorJSBean.setSpeed_shreshold(jsonObject.getInt("speed"));
                }

                if (jsonObject.has("interval")) {
                    mSensorJSBean.setUptate_interval_time(jsonObject.getInt("interval"));
                }

                int type = 0;
                if (jsonObject.has("type")) {
                    type = jsonObject.getInt("type");
                }
                if (type != 0) {
//                    TYPE_ACCELEROMETER=1
//                    TYPE_MAGNETIC_FIELD=2
                    mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(type), SensorManager.SENSOR_DELAY_NORMAL);
                }

                callBackForJS(jsInBean, true);

            } catch (JSONException jsonEx) {
                callBackForJS(jsInBean, false);
            }
        }
    }

    /**
     * 解注册
     *
     * @param json
     */
    public void ad_func_unregsensor(String json) {
        if (mHandler != null && mSensorManager != null) {
            ADJSInBean jsInBean = parseJsonArray(json);
            try {
//                JSONObject jsonObject = new JSONObject(jsInBean.getName());
                mSensorManager.unregisterListener(this);
                callBackForJS(jsInBean, true);
            } catch (Exception jsonEx) {
                callBackForJS(jsInBean, false);
            }
        }
    }

    private SensorAdJsBridge parseSensorJsonArray(String jsonString) {
        SensorAdJsBridge jsInBean = new SensorAdJsBridge();
        try {
            JSONArray ja = new JSONArray(jsonString);
            JSONObject jo = ja.getJSONObject(0);
            jsInBean.setName(jo.getString("name").trim());
            jsInBean.setCallback_id(jo.getString("callback_id").trim());
            jsInBean.setCallback(jo.getString("callback").trim());
            jsInBean.setFunc(jo.getString("func").trim());
        } catch (JSONException e) {
            e.printStackTrace();
        }
        LogInfo.log("lxx", "parseJsonArray jsInBean: " + jsInBean);
        return jsInBean;
    }

    /**
     * 获取广告信息
     *
     * @param json
     */
    public void ad_func_getAdInfo(String json) {
        ADJSInBean jsInBean = parseJsonArray(json);
        HashMap<String, Object> deviceInfo = new HashMap<String, Object>();
        deviceInfo.put("v_width", this.mRawWidth);
        deviceInfo.put("v_height", this.mRawHeight);
        deviceInfo.put("uuid", "");
        deviceInfo.put("pVersion", Commons.PVERSION);
        deviceInfo.put("type", "Phone");
        deviceInfo.put("pCode", Commons.PCODE);
        deviceInfo.put("device_info", Commons.DEVICE_INFO);
        deviceInfo.put("device_id", Commons.DEVICE_ID);
        deviceInfo.put("mac", Commons.MAC);
        if (mAdElement != null) {
            deviceInfo.put("clickUrl", mAdElement.getClickThrough());
        }

      /*  deviceInfo.put("deviceId", LetvConstant.Global.DEVICEID);
        deviceInfo.put("name", LetvUtil.getDeviceName());
        deviceInfo.put("type", "Phone");
        deviceInfo.put("version", LetvConstant.Global.VERSION);//主要针对TV
        HashMap<String,Integer> screen = new HashMap<String, Integer>();
        screen.put("width",LetvConstant.Global.screenWidth);
        screen.put("height",LetvConstant.Global.screenHeight);
        deviceInfo.put("screen", new JSONObject(screen));*/
//        jsCallBack(jsInBean, (new JSONObject(deviceInfo)).toString());
        callBackForJS(jsInBean, deviceInfo);
    }

    private void callBackForJS(String json, boolean isSuccess) {
        ADJSInBean adjsInBean = parseJsonArray(json);
        jsCallBack(adjsInBean, isSuccess ? RESULT_SUCCEED : RESULT_FAIL);
    }

    /**
     * 客户端操作完之后把状态返回给JS
     *
     * @param jsInBean
     * @param isSuccess 是否成功
     */
    private void callBackForJS(ADJSInBean jsInBean, boolean isSuccess) {
        jsCallBack(jsInBean, isSuccess ? RESULT_SUCCEED : RESULT_FAIL);
    }

    private void callBackForJS(ADJSInBean jsInBean, Map<String, Object> keyValuePairs) {
        jsCallBack(jsInBean, (new JSONObject(keyValuePairs)).toString());
    }

    /**
     * 解析JS传来的Json串
     * 注：[{"name":{...}},"callback_id":"...","callback":"...","func":"..."]，此格式是固定的，但是"name"字段的值每个方法都不一样
     */
    public ADJSInBean parseJsonArray(String jsonString) {
        ADJSInBean jsInBean = new ADJSInBean();
        try {
            JSONArray ja = new JSONArray(jsonString);
            JSONObject jo = ja.getJSONObject(0);
            jsInBean.setName(jo.getString("name").trim());
            jsInBean.setCallback_id(jo.getString("callback_id").trim());
            jsInBean.setCallback(jo.getString("callback").trim());
            jsInBean.setFunc(jo.getString("func").trim());
        } catch (JSONException e) {
            e.printStackTrace();
        }
        LogInfo.log("lxx", "parseJsonArray jsInBean: " + jsInBean);
        return jsInBean;
    }

    /**
     * javascrip回调
     *
     * @param jsInBean
     * @param result
     */
    private void jsCallBack(ADJSInBean jsInBean, String result) {
        if (jsInBean == null) {
            LogInfo.log("wlx", "jsInBean is null");
            return;
        }
        final String callString = buildupJSCallString(jsInBean.getCallback(), jsInBean.getCallback_id(), result);
        LogInfo.log("wlx", jsInBean.getFunc() + ":" + callString);
        mWebView.post(new Runnable() {
            @Override
            public void run() {
                mWebView.loadUrl(callString);
            }
        });
    }

    public void fireSensorEvent(Map<String, Object> eventMap) {
        final String callString = "javascript:LetvJSBridge.fireEvent('onSensorFire','" + (new JSONObject(eventMap).toString()) + "')";
        mWebView.post(new Runnable() {
            @Override
            public void run() {
                mWebView.loadUrl(callString);
            }
        });
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (mSensorJSBean == null) {
            mSensorManager.unregisterListener(this);
            return;
        }
        float[] values = event.values;
        if (values.length == 0) {
            return;
        }
        Map<String, Object> eventMap = null;
        int type = event.sensor.getType();
        switch (type) {
        case Sensor.TYPE_ACCELEROMETER: {
            eventMap = handlAccelerometer(event);
            break;
        }
        case Sensor.TYPE_MAGNETIC_FIELD: {
            eventMap = handlMagneticfield(event);
            break;
        }
        case Sensor.TYPE_LIGHT: {
            eventMap = handlLight(event);
            break;
        }
        case Sensor.TYPE_PROXIMITY: {
            eventMap = handProximity(event);
            break;
        }
        default: {
            LogInfo.log(TAG, "没有处理的传感器");
            break;
        }
        }
        if (null != eventMap && mRegistedSensorTypeList.contains(type)) {
            fireSensorEvent(eventMap);
        }
        if (mRegistedSensorTypeList.contains(SENSOR_TYPE_ORIENTATION)) {
            if (Sensor.TYPE_ACCELEROMETER == type
                    || Sensor.TYPE_MAGNETIC_FIELD == type) {
                eventMap = handleOrientation(event);
                fireSensorEvent(eventMap);
            }
        }
    }

    private Map<String, Object> handlAccelerometer(SensorEvent event) {
        Map<String, Object> eventMap = null;
        accelerometerValues = event.values;
        if ((Math.abs(event.values[0]) > 17 || Math.abs(event.values[1]) > 17 || Math
                .abs(event.values[2]) > 17)) {
            // 现在检测时间
            long currentUpdateTime = System.currentTimeMillis();
            if (currentUpdateTime - lastUpdateTime > mSensorJSBean
                    .getUptate_interval_time()) {
                lastUpdateTime = System.currentTimeMillis();
                eventMap = new HashMap<String, Object>();
                eventMap.put("type", event.sensor.getType() + "");
                eventMap.put("accuracy", event.accuracy + "");
                eventMap.put("timestamp", event.timestamp + "");
                eventMap.put("valuesize", event.values.length + "");
                for (int i = 0; i < event.values.length; ++i) {
                    eventMap.put("value" + i, event.values[i] + "");
                }
            }
        }
        return eventMap;
    }

    private Map<String, Object> handlMagneticfield(SensorEvent event) {
        Map<String, Object> eventMap = null;
        magneticFieldValues = event.values;
        if ((Math.abs(event.values[0]) > 17 || Math.abs(event.values[1]) > 17 || Math
                .abs(event.values[2]) > 17)) {
            // 现在检测时间
            long currentUpdateTime = System.currentTimeMillis();
            if (currentUpdateTime - lastUpdateTime > mSensorJSBean
                    .getUptate_interval_time()) {
                lastUpdateTime = System.currentTimeMillis();
                eventMap = new HashMap<String, Object>();
                eventMap.put("type", event.sensor.getType() + "");
                eventMap.put("accuracy", event.accuracy + "");
                eventMap.put("timestamp", event.timestamp + "");
                eventMap.put("valuesize", event.values.length + "");
                for (int i = 0; i < event.values.length; ++i) {
                    eventMap.put("value" + i, event.values[i] + "");
                }
            }
        }
        return eventMap;
    }

    private Map<String, Object> handlLight(SensorEvent event) {
        Map<String, Object> eventMap = null;
        // 现在检测时间
        long currentUpdateTime = System.currentTimeMillis();
        if (currentUpdateTime - lastUpdateTime > mSensorJSBean
                .getUptate_interval_time()) {
            lastUpdateTime = System.currentTimeMillis();
            eventMap = new HashMap<String, Object>();
            eventMap.put("type", event.sensor.getType() + "");
            eventMap.put("accuracy", event.accuracy + "");
            eventMap.put("timestamp", event.timestamp + "");
            eventMap.put("valuesize", event.values.length + "");
            if (event.values.length > 0) {
                eventMap.put("value" + 0, event.values[0] + "");
            }
        }
        return eventMap;
    }

    private Map<String, Object> handProximity(SensorEvent event) {
        Map<String, Object> eventMap = null;
        // 现在检测时间
        long currentUpdateTime = System.currentTimeMillis();
        if (currentUpdateTime - lastUpdateTime > mSensorJSBean
                .getUptate_interval_time()) {
            lastUpdateTime = System.currentTimeMillis();
            eventMap = new HashMap<String, Object>();
            eventMap.put("type", event.sensor.getType() + "");
            eventMap.put("accuracy", event.accuracy + "");
            eventMap.put("timestamp", event.timestamp + "");
            eventMap.put("valuesize", event.values.length + "");
            if (event.values.length > 0) {
                eventMap.put("value" + 0, event.values[0] + "");
            }
        }
        return eventMap;
    }

    private Map<String, Object> handleOrientation(SensorEvent event) {
        float[] values = new float[3];
        float[] R = new float[9];
        SensorManager.getRotationMatrix(R, null, accelerometerValues,
                magneticFieldValues);
        SensorManager.getOrientation(R, values);

        // 要经过一次数据格式的转换，转换为度
        values[0] = (float) Math.toDegrees(values[0]);
        for (int i = 0; i < values.length; i++) {
            values[i] = (float) Math.toDegrees(values[i]);
        }
        LogInfo.log(TAG, values[0] + "");

        if (values[0] >= -5 && values[0] < 5) {
            LogInfo.log(TAG, "正北");
        } else if (values[0] >= 5 && values[0] < 85) {
            LogInfo.log(TAG, "东北");
        } else if (values[0] >= 85 && values[0] <= 95) {
            LogInfo.log(TAG, "正东");
        } else if (values[0] >= 95 && values[0] < 175) {
            LogInfo.log(TAG, "东南");
        } else if ((values[0] >= 175 && values[0] <= 180)
                || (values[0]) >= -180 && values[0] < -175) {
            LogInfo.log(TAG, "正南");
        } else if (values[0] >= -175 && values[0] < -95) {
            LogInfo.log(TAG, "西南");
        } else if (values[0] >= -95 && values[0] < -85) {
            LogInfo.log(TAG, "正西");
        } else if (values[0] >= -85 && values[0] < -5) {
            LogInfo.log(TAG, "西北");
        }
        Map<String, Object> eventMap = null;
        // 现在检测时间
        long currentUpdateTime = System.currentTimeMillis();
        if (currentUpdateTime - lastUpdateTime > mSensorJSBean
                .getUptate_interval_time()) {
            lastUpdateTime = System.currentTimeMillis();
            eventMap = new HashMap<String, Object>();
            eventMap.put("type", SENSOR_TYPE_ORIENTATION + "");
            eventMap.put("accuracy", event.accuracy + "");
            eventMap.put("timestamp", event.timestamp + "");
            eventMap.put("valuesize", values.length + "");
            for (int i = 0; i < values.length; ++i) {
                eventMap.put("value" + i, values[i] + "");
            }
        }
        return eventMap;
    }

    public void onWebviewHide() {
        if (hasRegistSensor && mSensorManager != null) {
            mSensorManager.unregisterListener(this);
            hasRegistSensor = false;
        }

    }

    public void onWebviewShow() {
        if (null == mSensorManager || hasRegistSensor) {
            return;
        }
        mSensorManager.unregisterListener(this);
        hasRegistSensor = true;
        for (int i = 0; i < mRegistedSensorTypeList.size(); i++) {
            if (SENSOR_TYPE_ORIENTATION == mRegistedSensorTypeList.get(i)) {
                // 方向感应通过加速感应和磁力感应获取
                mSensorManager.registerListener(this, mSensorManager
                        .getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
                        SensorManager.SENSOR_DELAY_NORMAL);
                mSensorManager.registerListener(this, mSensorManager
                        .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
                        SensorManager.SENSOR_DELAY_NORMAL);
            } else {
                mSensorManager.registerListener(this, mSensorManager
                        .getDefaultSensor(mRegistedSensorTypeList.get(i)),
                        SensorManager.SENSOR_DELAY_NORMAL);
            }
        }
    }

    public void onDestory() {
        if (hasRegistSensor && mSensorManager != null) {
            mRegistedSensorTypeList.clear();
            mSensorManager.unregisterListener(this);
            mSensorManager = null;
        }
        mSensorJSBean = null;
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}
